package com.xsoft.web.util;


import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;


/**
 * <code>DES</code> �����㷨���ַ�ӽ��ܵı���ࡣ
 */
public class DESCrypto {
	

	/**
	 * ��ͨ�ַ���ܱ�ʶ��
	 */
	public static final Integer NORMAL_STRING = 1;
	
	/**
	 * ��Ҫ�ַ���ܱ�ʶ��
	 */
	public static final Integer IMPORTANT_STRING = 2;
	
	// �������͡�
	private static final String ENCRYPTO_TYPE = "DES";
	
	// ��ͨ�ַ������Կ
	private static final byte[] normalString = {
		(byte)0xda, (byte)0x0b, (byte)0xb0, (byte)0xad,
		(byte)0xa2, (byte)0x54, (byte)0x15, (byte)0xae
	};
	
	// ��Ҫ�ַ������Կ
	private static final byte[] importantString = {
		(byte)0xda, (byte)0x0a, (byte)0xb0, (byte)0xad,
		(byte)0xa2, (byte)0x34, (byte)0x15, (byte)0xae
	};
	
	private final static int  ENCODE_XORMASK = 0x62;
    private final static char ENCODE_CHAR_OFFSET1 = 'F';
    private final static char ENCODE_CHAR_OFFSET2 = 'A';
    
    /**
     * Ĭ�ϵĹ��췽����
     */
    DESCrypto() {
    }
	
	/**
	 * ���ܸ���ַ���{@link #decrypt(String, int)}�������н��ܡ�
	 * 
	 * @param input Ҫ���ܵ��ַ�
	 * @return ���ظ��ַ�����ġ�
	 */
	public static String encrypt(String input, int type) {
		byte[] cipherByte = null;
		try {
			SecretKeySpec deskey = null;
			if(type == NORMAL_STRING)
				deskey = new SecretKeySpec(normalString, ENCRYPTO_TYPE);
			else if(type == IMPORTANT_STRING) {
				deskey = new SecretKeySpec(importantString, ENCRYPTO_TYPE);
			}
			Cipher c1 = Cipher.getInstance(ENCRYPTO_TYPE);
			c1.init(Cipher.ENCRYPT_MODE, deskey);
			cipherByte = c1.doFinal(input.getBytes());
		} catch(Exception e) {
			e.printStackTrace();
		}
		return byte2hex(cipherByte);
	}
	
	/**
	 * ���ܸ���ַ�����ַ�Ϊ{@link #encrypt(String, int)}���ܵ��ַ�
	 * 
	 * @param input Ҫ���ܵ������ַ�
	 * @return ���ؽ��ܺ��ԭ���ַ�
	 */
	public static String decrypt(String input, int type) {
		byte[] cipherByte = null;
		try {
			SecretKeySpec deskey = null;
			if(type == NORMAL_STRING)
				deskey = new SecretKeySpec(normalString, ENCRYPTO_TYPE);
			else if(type == IMPORTANT_STRING) {
				deskey = new SecretKeySpec(importantString, ENCRYPTO_TYPE);
			}
			Cipher c1 = Cipher.getInstance(ENCRYPTO_TYPE);
			c1.init(Cipher.DECRYPT_MODE, deskey);
			cipherByte = c1.doFinal(hex2byte(input));
		} catch(Exception e) {
			return "";
		}
		return new String(cipherByte);
	}
	
	/**
	 * һ�����ټ��ļ����㷨������һ���ַ���{@link #decode(String)}�������ܡ�
	 * 
	 * @param info Ҫ���ܵ��ַ�
	 * @return ���ؼ��ܺ�����ġ�
	 */
	public static String encode(String info) {
		StringBuffer buf = new StringBuffer();
		if( info != null && !"".equals(info) ) {
			byte[] bytes = info.getBytes();
			int b;
			
			for (int n = 0; n < bytes.length; n++) {
                b = bytes[n] ^ (ENCODE_XORMASK + n);
                buf.append((char)(ENCODE_CHAR_OFFSET1 + (b & 0x0F)));
                buf.append((char)(ENCODE_CHAR_OFFSET2 + ((b >> 4) & 0x0F)));
            }
		}
		return buf.toString();
	}
	
	/**
	 * һ�����ټ��ļ��ܽ����㷨������һ���ַ���{@link #encode(String)}�������ܡ�
	 * 
	 * @param info Ҫ���ܵ��ַ�
	 * @return ���ؽ��ܺ��ԭ�ġ�
	 */
	public static String decode(String info) {
		if( info == null || info.length() <= 0 ) {
			return "";
		}
		
		char[] chars = info.toCharArray();
        byte[] bytes = new byte[chars.length / 2];
        
        int b;
        for (int n = 0, m = 0; n < bytes.length; n++) {
            b = chars[m++] - ENCODE_CHAR_OFFSET1;
            b |= (chars[m++] - ENCODE_CHAR_OFFSET2) << 4;
            bytes[n] = (byte)(b ^ (ENCODE_XORMASK + n));
        }

        return new String(bytes);
	}
	
	private static String byte2hex(byte[] b) { 
		String hs = ""; 
		String stmp = ""; 
		for (int i = 0; i < b.length; i++) { 
		stmp = Integer.toHexString(b[i] & 0xFF); 
			if (stmp.length() == 1) { 
				hs += "0" + stmp; 
			} 
			else { 
				hs += stmp; 
			} 
		} 
		return hs.toUpperCase(); 
	} 

	private static byte[] hex2byte(String hex) throws IllegalArgumentException { 
		if (hex.length() % 2 != 0) { 
			throw new IllegalArgumentException(); 
		} 
		char[] arr = hex.toCharArray(); 
		byte[] b = new byte[hex.length() / 2]; 
		for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) { 
			String swap = "" + arr[i++] + arr[i]; 
			int byteint = Integer.parseInt(swap, 16) & 0xFF; 
			b[j] = new Integer(byteint).byteValue(); 
		} 
		return b; 
	}
}
